<script setup lang="ts">
import MyComp from "../components/marker.vue";
import PoiMyComp from "../components/poiMarker.vue";
import { Close } from "@element-plus/icons-vue";
import {
  onMounted,
  onUnmounted,
  ref,
  nextTick,
  reactive,
  createApp
} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import { ElForm, ElMessage, ElMessageBox, ElNotification } from "element-plus";
import { getCenter } from "@/views/map/utils/index";
import { v4 } from "uuid";
import { cloneDeep } from "@pureadmin/utils";
import { editVppUserList } from "@/api/vppUser";
const createHTML = (comp, props) => {
  const element = document.createElement("div");
  const app = createApp(comp, props);
  app.mount(element);

  return {
    element,
    app
  };
};
const props = defineProps({
  activeVppUserId: {
    type: String
  },
  handleStatus: {
    type: String,
    default: "add"
  },
  vppUserData: {
    type: Object
  }
});
const myAmap = ref(null);
const map = ref(null);
const mouseTool = ref(null);
const overlays = ref([]);
const markers = ref([]);
const loading = ref(true);
// 处于绘制区块中的状态
const drawStatus = ref(false);
// 处于标注中的状态
const clickStatus = ref(false);
const clickCount = ref(0);
const drawSetShow = ref(false);
const ruleForm = ref(null);
// 当前绘制完毕的图形的中心点
const center = ref([]);
// 当前绘制完毕的图形
const activeObj = ref(null);
// 当前鼠标移入 双击想操作的区域
const activeHandleObj = ref(null);
// 开启编辑的区块的返回值
const polyEditor = ref(null);
// 区块编辑状态
const editStatus = ref(false);
// 抽屉出来后表单状态 add edit
const formStatus = ref("add");
// 单击marker 出现编辑的active
const activeMarker = ref(null);
const form = reactive({
  data: {
    name: ""
  },
  rules: {
    name: [{ required: true, message: "区域名称不能为空", trigger: "blur" }]
  }
});
const cancel = () => {
  form.data.name = "";
  center.value = [];
  // activeObj.value.destroy();
  map.value.remove([activeObj.value]);
  clickCount.value = 0;
  mouseTool.value.close(false);
  drawStatus.value = false;
  nextTick(() => {
    ruleForm.value.clearValidate();
    drawSetShow.value = false;
  });
};
const beforeClose = d => {
  form.data.name = "";
  center.value = [];
  // activeObj.value.destroy();
  map.value.remove([activeObj.value]);
  clickCount.value = 0;
  mouseTool.value.close(false);
  drawStatus.value = false;
  ruleForm.value.clearValidate();
  drawSetShow.value = false;
  d();
};

const submit = () => {
  ruleForm.value.validate(async valid => {
    if (valid) {
      if (formStatus.value === "add") {
        let uuid = v4();
        let marker = new myAmap.value.Marker({
          map: map.value,
          position: center.value,
          anchor: "bottom-center"
        });
        marker.setLabel({
          direction: "right",
          offset: new myAmap.value.Pixel(10, 0), //设置文本标注偏移量
          content: `<div class='info'>${form.data.name}</div>` //设置文本标注内容
        });
        marker.setTitle(form.data.name);
        marker.setExtData({
          uuid: uuid,
          data: cloneDeep(form.data)
        });
        marker.on("click", e => {
          formStatus.value = "edit";
          drawFormHandle(marker);
        });
        activeObj.value.setExtData({
          uuid: uuid
        });
        // activeObj.value._opts.data = {
        //   uuid: uuid
        // };
        markers.value.push(marker);
        overlays.value.push(activeObj.value);

        clickCount.value = 0;
        drawStatus.value = false;
        mouseTool.value.close(false);
      } else {
        activeMarker.value.setLabel({
          direction: "right",
          offset: new myAmap.value.Pixel(10, 0), //设置文本标注偏移量
          content: `<div class='info'>${form.data.name}</div>` //设置文本标注内容
        });
        activeMarker.value.setTitle(form.data.name);
        let oriData = activeMarker.value.getExtData();
        activeMarker.value.setExtData({
          uuid: oriData.uuid,
          data: cloneDeep(form.data)
        });
      }
      drawSetShow.value = false;
    }
  });
};
const resetForm = () => {
  form.data.name = "";
  nextTick(() => {
    ruleForm.value.clearValidate();
  });
};
const emitClose = (data, type) => {
  if (type === "marker") {
    map.value.remove(vppUserMarker.value);
    vppUserMarker.value = [];
  }
  if (type === "area") {
    let item = overlays.value.find(citem => {
      return citem.getExtData().uuid === data.uuid;
    });
    let index = overlays.value.findIndex(citem => {
      return citem.getExtData().uuid === data.uuid;
    });
    let aData = item.getExtData();
    let mitem = markers.value.find(citem => {
      return citem.getExtData().uuid === aData.uuid;
    });
    let mIndex = markers.value.findIndex(citem => {
      return citem.getExtData().uuid === aData.uuid;
    });
    map.value.remove([item, mitem]);
    overlays.value.splice(index, 1);
    markers.value.splice(mIndex, 1);
  }
};
const addArea = () => {
  let areaData = {
    data: cloneDeep(props.vppUserData),
    uuid: v4()
  };
  const { app, element } = createHTML(MyComp, {
    name: props.vppUserData.name,
    areaData: areaData,
    emitClose: emitClose,
    handleStatus: props.handleStatus
  });
  let marker = new myAmap.value.Marker({
    map: map.value,
    position: center.value,
    anchor: "bottom-center",
    content: element
  });
  marker.setTitle(props.vppUserData.name);
  marker.setExtData(areaData);
  marker.on("click", e => {});
  activeObj.value.setExtData(areaData);
  markers.value.push(marker);
  overlays.value.push(activeObj.value);
  clickCount.value = 0;
  drawStatus.value = false;
  mouseTool.value.close(false);
};
const placeSearch = ref(null);
const auto = ref(null);
const state = ref("");
const querySearchAsync = (str, cb) => {
  if (!str) {
    auto.value.close();
    return false;
  }
  placeSearch.value.search(str, (s, r) => {
    if (r.info === "OK") {
      cb(
        r.poiList.pois.map(item => ({
          value: item.name,
          label: item.name,
          ...item
        }))
      );
    } else {
      cb([]);
    }
  });
};
const clearSearch = () => {
  map.value.remove(searchMarker.value);
  searchMarker.value = [];
  state.value = "";
};
const handleSelect = item => {
  map.value.setCenter([item.location.lng, item.location.lat]);
  let marker = new myAmap.value.Marker({
    position: [item.location.lng, item.location.lat],
    anchor: "bottom-center",
    offset: new myAmap.value.Pixel(0, 0)
  });
  marker.setMap(map.value);
  // 设置鼠标划过点标记显示的文字提示
  marker.setTitle(item.name);
  // 设置label标签
  // label默认蓝框白底左上角显示，样式className为：amap-marker-label
  marker.setLabel({
    direction: "right",
    offset: new AMap.Pixel(10, 0), //设置文本标注偏移量
    content: `<div class='info'>${item.name}</div>` //设置文本标注内容
  });
  searchMarker.value.push(marker);
};
const showMap = () => {
  AMapLoader.load({
    key: "6c12e6d70ad9444d38cf9aafcc7a4393", // 申请好的Web端开发者Key，首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    plugins: ["AMap.MouseTool", "AMap.PolygonEditor", "AMap.PlaceSearch"] // 需要使用的的插件列表，如比例尺'AMap.Scale'等
  })
    .then(AMap => {
      myAmap.value = AMap;
      map.value = new AMap.Map("map-container", {
        // 设置地图容器id
        viewMode: "2D", // 是否为3D地图模式
        zoom: 12, // 初始化地图级别
        center: props.vppUserData.longitude
          ? [props.vppUserData.longitude, props.vppUserData.latitude]
          : [125.3245, 43.886841] // 初始化地图中心点位置
      });
      placeSearch.value = new AMap.PlaceSearch({
        city: "全国",
        pageSize: 30, // 单页显示结果条数
        pageIndex: 1, // 页码
        citylimit: false, // 是否强制限制在设置的城市内搜索
        autoFitView: true
      });
      mouseTool.value = new AMap.MouseTool(map.value);
      mouseTool.value.on("draw", function (e) {
        let paths = e.obj.getPath();
        if (paths.length < 3) {
          clickCount.value = 0;
          map.value.remove([e.obj]);
          return;
        }
        if (paths.length !== clickCount.value) {
          map.value.remove([e.obj]);
          clickCount.value = 0;
          return;
        }
        center.value = getCenter(e.obj._opts.path);
        activeObj.value = e.obj;
        e.obj.on("click", ev => {
          if (clickStatus.value) {
            setMarker(ev);
          }
        });
        e.obj.on("mouseover", ev => {
          tipShow.value = true;
          let oData = e.obj.getExtData();
          tipData.data = oData.data;
          ev.target.setOptions({
            fillOpacity: 0.7,
            fillColor: "#7bccc4",
            strokeColor: "#80d8ff"
          });
        });
        e.obj.on("mouseout", ev => {
          tipShow.value = false;
          ev.target.setOptions({
            fillOpacity: 0.7,
            fillColor: "#00b0ff",
            strokeColor: "#80d8ff"
          });
        });
        e.obj.on("dblclick", ev => {
          if (props.handleStatus === "look") return;
          if (editStatus.value) return;
          if (clickStatus.value) return;
          editStatus.value = true;
          activeHandleObj.value = e.obj;
          polyEditor.value = new myAmap.value.PolygonEditor(map.value, e.obj);
          polyEditor.value.open();
          polyEditor.value.on("addnode", function (event) {
            //切忌不要通过event的路径去拿path，tm路径居然会不定时变，
            //辛亏上线前发现了。可以用polygon.getPath()
          });

          polyEditor.value.on("adjust", function (event) {});

          polyEditor.value.on("removenode", function (event) {});

          polyEditor.value.on("end", function (event) {
            // event.target 即为编辑后的多边形对象
          });
        });
        addArea();
        // drawSetShow.value = true;
        // formStatus.value = "add";
        // resetForm();
      });
      map.value.on("complete", function () {
        //地图图块加载完成后触发

        echoMapData();
        loading.value = false;
      });
      map.value.on("click", e => {
        if (drawStatus.value) {
          clickCount.value += 1;
        }
        if (clickStatus.value) {
          setMarker(e);
        }
      });
      map.value.on("dblclick", e => {});
      map.value.on("rightclick", e => {});
    })
    .catch(e => {
      console.log(e);
    });
};
const mainBox = ref(null);
onMounted(() => {
  window._AMapSecurityConfig = {
    securityJsCode: "895be63184d6a961299d262ebfcf2429"
  };
  mainBox.value.addEventListener("contextmenu", function (event) {
    // 阻止默认的右键菜单
    event.preventDefault();
  });
});
const draw = () => {
  if (clickStatus.value || editStatus.value) return;
  if (overlays.value.length > 0) return;
  clickStatus.value = false;
  drawStatus.value = true;
  clickCount.value = 0;
  mouseTool.value.polygon({
    fillOpacity: 0.7,
    fillColor: "#00b0ff",
    strokeColor: "#80d8ff"
    //同Polygon的Option设置
  });
};
const stopDraw = () => {
  if (clickCount.value > 0) {
    ElNotification({
      title: "系统提示",
      message: "请绘制完整图形!",
      type: "warning"
    });
    return;
  }
  clickCount.value = 0;
  drawStatus.value = false;
  mouseTool.value.close(false);
};
const clearAll = () => {
  map.value.remove(overlays.value);
  map.value.remove(markers.value);
  map.value.remove(vppUserMarker.value);
  overlays.value = [];
  markers.value = [];
  vppUserMarker.value = [];
};
const stopEdit = () => {
  if (!editStatus.value) return;
  let paths = activeHandleObj.value.getPath();
  let areaData = activeHandleObj.value.getExtData();
  // 停止编辑后计算中心点 挪动marker
  let center = getCenter(paths.map(item => [item.lng, item.lat]));
  markers.value.forEach(item => {
    let moData = item.getExtData();
    if (moData.uuid === areaData.uuid) {
      item.setPosition(center);
    }
  });
  polyEditor.value && polyEditor.value.close();
  editStatus.value = false;
};
const saveAll = async () => {
  if (drawStatus.value || clickStatus.value || editStatus.value) {
    ElMessage({
      message: "请停止操作状态再进行保存!",
      type: "error"
    });
    return;
  }
  const data = cloneDeep(props.vppUserData);
  if (markers.value.length && overlays.value.length) {
    // 保存 marker position  表单数据
    let lnglatsAll = [];
    overlays.value.forEach(item => {
      let lnglatItem = [];
      item.getPath().forEach(c => {
        lnglatItem.push(`${c.lng},${c.lat}`);
      });
      lnglatsAll.push(lnglatItem.join(";"));
    });
    // 电子围栏
    data.fenceXy = lnglatsAll.join("@");
    if (vppUserMarker.value.length) {
      // 经纬度中心点
      data.longitude = vppUserMarker.value[0].getPosition().lng;
      data.latitude = vppUserMarker.value[0].getPosition().lat;
    } else {
      // 未标注经纬度中心点 则 取 标注区块的中心点
      let item = overlays.value[0];
      let center = getCenter(item.getPath().map(item => [item.lng, item.lat]));
      data.longitude = center[0];
      data.latitude = center[1];
    }
    // else {
    //   if(!props.vppUserData.longitude && !props.vppUserData.latitude) {
    //
    //   }
    // }
    loading.value = true;
    await editVppUserList(data);
    ElNotification({
      title: "系统提示",
      message: "用户信息更新成功",
      type: "success"
    });
    loading.value = false;
  } else {
    if (vppUserMarker.value.length) {
      loading.value = true;
      // 经纬度中心点
      data.longitude = vppUserMarker.value[0].getPosition().lng;
      data.latitude = vppUserMarker.value[0].getPosition().lat;
      data.fenceXy = "";
      await editVppUserList(data);
      ElNotification({
        title: "系统提示",
        message: "用户信息更新成功",
        type: "success"
      });
      loading.value = false;
    } else {
      loading.value = true;
      data.longitude = null;
      data.latitude = null;
      data.fenceXy = "";
      await editVppUserList(data);
      ElNotification({
        title: "系统提示",
        message: "用户信息更新成功",
        type: "success"
      });
      loading.value = false;
    }
  }
};
const searchMarker = ref([]);
const echoMapData = () => {
  map.value.remove([
    ...markers.value,
    ...vppUserMarker.value,
    ...overlays.value
  ]);
  markers.value = [];
  vppUserMarker.value = [];
  overlays.value = [];
  if (props.vppUserData.longitude && props.vppUserData.latitude) {
    setMarker({
      lnglat: {
        lng: props.vppUserData.longitude,
        lat: props.vppUserData.latitude
      }
    });
    map.value.setCenter([
      props.vppUserData.longitude,
      props.vppUserData.latitude
    ]);
  }
  if (props.vppUserData.fenceXy) {
    let data = {
      o: props.vppUserData.fenceXy.split("@")
    };
    if (data.o && data.o.length) {
      for (let i = 0; i < data.o.length; i++) {
        let item = data.o[i];
        let paths = item
          .split(";")
          .map(z => [parseFloat(z.split(",")[0]), parseFloat(z.split(",")[1])]);
        let polygon = new myAmap.value.Polygon({
          path: paths,
          fillColor: "#00b0ff",
          strokeOpacity: 1,
          fillOpacity: 0.7,
          strokeColor: "#80d8ff",
          strokeWeight: 1,
          strokeStyle: "dashed",
          strokeDasharray: [5, 5]
        });
        polygon.on("click", ev => {
          if (clickStatus.value) {
            setMarker(ev);
          }
        });
        polygon.on("mouseover", ev => {
          tipShow.value = true;
          let oData = polygon.getExtData();
          tipData.data = oData.data;
          polygon.setOptions({
            fillOpacity: 0.7,
            fillColor: "#7bccc4",
            strokeColor: "#80d8ff"
          });
        });
        polygon.on("mouseout", ev => {
          tipShow.value = false;
          polygon.setOptions({
            fillOpacity: 0.7,
            fillColor: "#00b0ff",
            strokeColor: "#80d8ff"
          });
        });
        polygon.on("dblclick", ev => {
          if (props.handleStatus === "look") return;
          if (editStatus.value) return;
          if (clickStatus.value) return;
          editStatus.value = true;
          activeHandleObj.value = polygon;
          polyEditor.value = new myAmap.value.PolygonEditor(map.value, polygon);
          polyEditor.value.open();
          polyEditor.value.on("addnode", function (event) {
            //切忌不要通过event的路径去拿path，tm路径居然会不定时变，
            //辛亏上线前发现了。可以用polygon.getPath()
          });

          polyEditor.value.on("adjust", function (event) {});

          polyEditor.value.on("removenode", function (event) {});

          polyEditor.value.on("end", function (event) {
            // event.target 即为编辑后的多边形对象
          });
        });
        let areaData = {
          data: cloneDeep(props.vppUserData),
          uuid: v4()
        };
        polygon.setExtData(areaData);
        map.value.add(polygon);
        overlays.value.push(polygon);

        const { app, element } = createHTML(MyComp, {
          name: props.vppUserData.name,
          areaData: areaData,
          emitClose: emitClose,
          handleStatus: props.handleStatus
        });
        let marker = new myAmap.value.Marker({
          map: map.value,
          position: getCenter(paths),
          anchor: "bottom-center",
          content: element
        });
        marker.setTitle(props.vppUserData.name);
        marker.setExtData(areaData);
        markers.value.push(marker);
      }
    }
  }
};
const drawFormHandle = marker => {
  let data = marker.getExtData();
  activeMarker.value = marker;
  drawSetShow.value = true;
  form.data = cloneDeep(data.data);
};
const delThis = () => {
  // 根据 activeMarker 删除 区域 marker
  let data = activeMarker.value.getExtData();
  let activeArea = overlays.value.find(item => {
    let aData = item.getExtData();
    if (aData.uuid === data.uuid) {
      return true;
    }
  });
  if (activeArea) {
    // 地图删除
    map.value.remove([activeMarker.value, activeArea]);
    // 数组删除
    let oIndex = overlays.value.findIndex(item => {
      return item.getExtData().uuid === data.uuid;
    });
    overlays.value.splice(oIndex, 1);
    let mIndex = markers.value.findIndex(item => {
      return item.getExtData().uuid === data.uuid;
    });
    markers.value.splice(mIndex, 1);
    activeMarker.value = null;
    activeObj.value = null;
    activeHandleObj.value = null;
    drawSetShow.value = false;
  }
};
const tipShow = ref(false);
const tipData = reactive({
  data: null
});
onUnmounted(() => {
  map.value?.destroy();
});
defineExpose({
  showMap,
  map,
  echoMapData
});
const clickSet = v => {
  if (drawStatus.value || editStatus.value) return;
  clickStatus.value = v;
};
const vppUserMarker = ref([]);
const setMarker = data => {
  let areaData = {
    data: cloneDeep(props.vppUserData),
    uuid: v4()
  };
  const { app, element } = createHTML(PoiMyComp, {
    name: props.vppUserData.name,
    areaData: areaData,
    emitClose: emitClose,
    handleStatus: props.handleStatus
  });
  let marker = new myAmap.value.Marker({
    map: map.value,
    position: [data.lnglat.lng, data.lnglat.lat],
    anchor: "bottom-center",
    content: element
  });
  marker.setTitle(props.vppUserData.name);
  marker.setzIndex(999);
  marker.setExtData(areaData);
  if (vppUserMarker.value.length) {
    map.value.remove(vppUserMarker.value);
    vppUserMarker.value = [];
  }
  vppUserMarker.value.push(marker);
};
</script>

<template>
  <div ref="mainBox" v-loading="loading" class="main w-full">
    <div
      v-if="handleStatus === 'add' || handleStatus === 'edit'"
      class="absolute left-0 top-0 z-10 w-full flex justify-between"
    >
      <div>
        <el-button
          v-if="!drawStatus && !clickStatus"
          type="primary"
          @click="clickSet(true)"
          >标注用户经纬度</el-button
        >
        <el-button
          v-if="!drawStatus && clickStatus"
          type="danger"
          @click="clickSet(false)"
          >停止标注用户经纬度</el-button
        >
        <el-button v-if="!drawStatus" type="primary" @click="draw"
          >绘制围栏</el-button
        >
        <el-button v-if="drawStatus" type="danger" @click="stopDraw"
          >停止绘制</el-button
        >
        <el-button type="primary" @click="clearAll">清空所有</el-button>
        <el-button v-if="editStatus" type="danger" @click="stopEdit"
          >停止编辑</el-button
        >
        <el-button type="primary" @click="saveAll">保存</el-button>
      </div>
      <div>
        <el-autocomplete
          ref="auto"
          v-model="state"
          style="width: 240px"
          :debounce="500"
          :fetch-suggestions="querySearchAsync"
          placeholder="输入关键词会自动进行搜索"
          @select="handleSelect"
        />
        <el-button class="ml-[12px]" type="primary" @click="clearSearch"
          >清空搜索结果</el-button
        >
      </div>
    </div>
    <div v-if="tipShow" class="absolute right-0 top-0 z-10">
      <el-card>
        {{ tipData.data ? tipData.data.name : "无数据" }}
      </el-card>
    </div>
    <div id="map-container" />
    <el-drawer
      v-model="drawSetShow"
      title="区域信息设置"
      :close-on-click-modal="false"
      :before-close="beforeClose"
      size="20%"
    >
      <div>
        <el-form
          ref="ruleForm"
          label-width="80px"
          :model="form.data"
          :rules="form.rules"
        >
          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="区域名称" prop="name">
                <el-input v-model="form.data.name" placeholder="区域名称" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-popconfirm
            v-if="formStatus === 'edit'"
            width="200px"
            title="确定删除该区块吗？"
            @confirm="delThis"
          >
            <template #reference>
              <el-button type="danger"> 删除该区块 </el-button>
            </template>
          </el-popconfirm>
          <el-button v-if="formStatus === 'add'" @click="cancel"
            >取消</el-button
          >
          <el-button type="primary" @click="submit"> 确认 </el-button>
        </span>
      </template>
    </el-drawer>
  </div>
</template>

<style scoped lang="scss">
.main {
  position: relative;
  width: 100%;
  height: 70vh;

  #map-container {
    position: relative;
    width: 100%;
    height: 100%;
  }
}
</style>
